#include "ej_event.h"

/* 事件对象 */
typedef struct EventNode {
    uint32_t event_id;
    void* message;
    size_t msg_size;
    uint64_t trigger_time;
    TaskContext_t* target;
    struct EventNode* next;
} EventNode_t;

/* 时间轮结构 */
#define TIME_WHEEL_SIZE 64
typedef struct {
    EventNode_t* slots[TIME_WHEEL_SIZE];
    uint64_t base_time;
} TimeWheel_t;

/* 全局状态 */
static struct {
    TimeWheel_t timer;
    EventNode_t* ready_queue;
    EventNode_t* pool;
    size_t pool_size;
    const EventPlatform_t* platform;
    bool initialized;
} system_state;

/* 内部辅助函数 */
static EventNode_t* alloc_event(void) 
{
    EventNode_t* event = system_state.platform->mem_alloc(sizeof(EventNode_t));
    if(event) memset(event, 0, sizeof(EventNode_t));
    return event;
}

static void free_event(EventNode_t* event) 
{
    if(event->message) 
	{
        system_state.platform->mem_free(event->message);
    }
    system_state.platform->mem_free(event);
}

static void schedule_event(EventNode_t* event) 
{
    const uint64_t now = system_state.platform->get_system_time();
    const uint64_t delta = event->trigger_time - now;
    
    uint32_t slot = (delta + system_state.timer.base_time) % TIME_WHEEL_SIZE;
    
    system_state.platform->enter_critical();
    event->next = system_state.timer.slots[slot];
    system_state.timer.slots[slot] = event;
    system_state.platform->exit_critical();
}

/* API实现 */
void ej_event_init(const EventPlatform_t* platform) 
{
    if(system_state.initialized) return;

    system_state.platform = platform;
    system_state.timer.base_time = platform->get_system_time();
    system_state.initialized = true;
}

void ej_event_create_task(TaskContext_t* ctx, event_handler_t handler) 
{
    ctx->handler = handler;
    ctx->pending_count = 0;
}

void ej_event_publish_impl(TaskContext_t* ctx, uint32_t event_id, void* msg, 
                          size_t msg_size, uint32_t delay_ms, bool from_isr) 
{
    const EventPlatform_t* p = system_state.platform;

	p->enter_critical();
	
    /* 分配事件对象 */
    EventNode_t* event = alloc_event();
    if(!event) 
	{
		p->exit_critical();
		return;
	}

	if ((msg_size > 0) && (NULL != msg))
	{
	    /* 复制消息内容 */
	    event->message = p->mem_alloc(msg_size);
	    if(!event->message) {
	        free_event(event);
			p->exit_critical();
	        return;
	    }
	    memcpy(event->message, msg, msg_size);		
	}
	else
	{
		event->message = NULL;
	}

    /* 填充事件数据 */
    event->event_id = event_id;
    event->msg_size = msg_size;
    event->target = ctx;
    event->trigger_time = p->get_system_time() + delay_ms;

	schedule_event(event);

    ctx->pending_count++;
	
	p->exit_critical();
	
}

void ej_event_publish_datas(TaskContext_t* ctx, uint32_t event_id, void* msg, 
                     size_t msg_size, uint32_t delay_ms) {
    ej_event_publish_impl(ctx, event_id, msg, msg_size, delay_ms, false);
}

void ej_event_publish(TaskContext_t* ctx, uint32_t event_id, uint32_t delay_ms) {
    ej_event_publish_impl(ctx, event_id, NULL, 0, delay_ms, false);
}

void ej_event_publish_datas_isr(TaskContext_t* ctx, uint32_t event_id, void* msg, 
                         size_t msg_size, uint32_t delay_ms) {
    ej_event_publish_impl(ctx, event_id, msg, msg_size, delay_ms, true);
}

void ej_event_publish_isr(TaskContext_t* ctx, uint32_t event_id, uint32_t delay_ms) {
    ej_event_publish_impl(ctx, event_id, NULL, 0, delay_ms, true);
}

void ej_event_process(void) {
    const EventPlatform_t* p = system_state.platform;
    const uint64_t now = p->get_system_time();
    const uint32_t slot = (now - system_state.timer.base_time) % TIME_WHEEL_SIZE;

    /* 处理到期事件 */
    p->enter_critical();
    EventNode_t** ptr = &system_state.timer.slots[slot];
    while(*ptr) {
        if((*ptr)->trigger_time <= now) {
            EventNode_t* ready = *ptr;
            *ptr = ready->next;
            
            ready->next = system_state.ready_queue;
            system_state.ready_queue = ready;
            ready->target->pending_count--;
        } else {
            ptr = &(*ptr)->next;
        }
    }
    p->exit_critical();

    /* 处理就绪队列 */
    while(system_state.ready_queue) {
        EventNode_t* event = system_state.ready_queue;
        system_state.ready_queue = event->next;

        if(event->target->handler) {
            event->target->handler(event->event_id, event->message, event->msg_size);
        }

        free_event(event);
    }
}

void ej_event_cancel_impl(TaskContext_t* ctx, uint32_t event_id, bool from_isr) 
{
    const EventPlatform_t* p = system_state.platform;

    p->enter_critical();
    for(int i=0; i<TIME_WHEEL_SIZE; i++) 
	{
        EventNode_t** prev = &system_state.timer.slots[i];
        while(*prev) 
		{
            if((*prev)->target == ctx && (*prev)->event_id == event_id) 
			{
                EventNode_t* to_remove = *prev;
                *prev = to_remove->next;
                free_event(to_remove);
                ctx->pending_count--;
            } else {
                prev = &(*prev)->next;
            }
        }
    }
    p->exit_critical();
}

void ej_event_cancel(TaskContext_t* ctx, uint32_t event_id) {
    ej_event_cancel_impl(ctx, event_id, false);
}

void ej_event_cancel_isr(TaskContext_t* ctx, uint32_t event_id) {
    ej_event_cancel_impl(ctx, event_id, true);
}


